<template>
  <div class="number-alignment">
    <div class="decrease" :class="{'disabled': min >= alignVal || readonly}" @click="decreaseNumber">-</div>
    <input type="text" 
      class="alignment" 
      :value="alignVal"
      @focus="setMask"
      @input="inputNumber($event.target.value)" 
      :readonly="readonly">
    <div class="increase" :class="{'disabled': max <= alignVal || readonly}" @click="increaseNumer">+</div>
    <!-- <div class="mask" v-if="showList" @click.stop="hideMask"></div> -->
  </div>
</template>

<script>
export default {
  props: {
    // 当前值
    value: {
      type: Number,
      default: 0
    },
    // 每次增加的位数，当前每次增加1
    step: {
      type: Number,
      default: 1
    },
    // 最大值
    max: {
      type: Number,
      default: 0
    },
    // 最小值
    min: {
      type: Number,
      default: 0
    },
    // 保留几位有效数字
    digit: {
      type: Number,
      default: 0
    },
    // 可编辑 true：不可编辑，false：可编辑
    readonly: {
      type: Boolean,
      default: true
    },
    // 是否是可编辑状态
    number: {
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      alignVal: this.value,
      showList: false
    }
  },
  mounted() {
    this.alignVal = this.value
  },
  /**
    * 此处需要使用监听，如果不用监听，那么没办法获取父级的值
    */
  watch: {
    value(newValue, oldValue) {
      this.alignVal = this.value
    }
  },
  methods: {
    /**
      * 展示遮罩层
      */
    setMask() {
      this.showList = true
    },

    /**
      * 隐藏遮罩层
      */
    hideMask() {
      setTimeout(() => {
        this.showList = false
      }, 100)
    },

    /**
      * 按照步长增加数值
      */
    increaseNumer() {
      // 如果是只读，则不处理
      if (this.readonly) {
        return
      }

      // 如果减去步长小于最小值，则赋值为最小值，检验失败
      if (!this.checkNumber(1)) {
        return
      }

      // 按照步长累加
      this.alignVal = this.alignVal + this.step
      this.$emit('type', 1)
      this.$emit('input', this.alignVal)
      this.$emit('on-change', this.alignVal)
    },
    /**
      * 输入值，只能输入数值
      */
    inputNumber(alignVal) {
      // 获取当前输入值
      this.alignVal = Number(alignVal)

      // 如果减去步长小于最小值，则赋值为最小值，检验失败
      if (!this.checkNumber(3)) {
        return
      }

      this.$emit('type', 3)
      this.$emit('input', this.alignVal)
      this.$emit('on-change', this.alignVal)
      this.alignVal = this.value
    },
    /**
      * 按照步长减小数值
      */
    decreaseNumber() {
      // 如果是只读，则不处理
      if (this.readonly) {
        return
      }

      // 如果值为0，则不能点击
      if (!this.alignVal) {
        return
      }

      // 如果减去步长小于最小值，则赋值为最小值，检验失败
      if (!this.checkNumber(2)) {
        return
      }

      // 按照步长减少
      this.alignVal = this.alignVal - this.step
      this.$emit('type', 2)
      this.$emit('input', this.alignVal)
      this.$emit('on-change', this.alignVal)
    },
    /**
      * 检测数值是不是符合要求，将不符合条件的值转换成正确的值
      *
      * @param { Object } type 1: 点击的是新增，2: 点击的是减小
      */
    checkNumber(type) {
      // 如果减去步长小于最小值，则赋值为最小值
      if (this.alignVal - this.step <= this.min && type == 2) {
        this.alignVal = this.min
        this.$emit('input', this.alignVal)
        this.$emit('on-change', this.alignVal)
        return false
      }

      // 如果减去步长小于最小值，则赋值为最小值
      if (this.alignVal - this.step < this.min && type == 3) {
        this.alignVal = this.min
        this.$emit('input', this.alignVal)
        this.$emit('on-change', this.alignVal)
        return false
      }

      // 如果减去步长大于最大值，则赋值为最大值
      if (this.alignVal + this.step > this.max && type == 1) {
        this.$toast('不得大于库存量')
        this.alignVal = this.max
        this.$emit('input', this.alignVal)
        this.$emit('on-change', this.alignVal)
        return false
      }

      // 如果输入的值超过最大值，则赋值为最大值
      if (this.alignVal > this.max && type == 3) {
        this.$toast('不得大于库存量')
        this.alignVal = this.max
        this.$emit('input', this.alignVal)
        this.$emit('on-change', this.alignVal)
        return false
      }

      // 将当前值变成字符串
      // 先把非数字的都替换掉，除了数字和.
      let v = ('' + this.alignVal).replace(/[^\d.]/g, '')

      // 必须保证第一个为数字而不是.
      v = v.replace(/^\./g, '')

      // 保证只有出现一个.而没有多个.
      v = v.replace(/\.{2,}/g, '')

      // 保证.只出现一次，而不能出现两次以上
      v = v.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.')

      // 如果值不存在，则抛出
      if (!v) {
        this.alignVal = 0
        this.$emit('input', this.alignVal)
        this.$emit('on-change', this.alignVal)
        return false
      }

      // 格式化
      this.alignVal = parseFloat(parseFloat(v).toFixed(this.digit))
      return true
    }
  }
}
</script>

<style lang="scss" scoped>
.number-alignment {
  border: 1px solid #CCC;
  display: inline-block;
  overflow: hidden;
  width: auto;
  height: 22px;
  
  div {
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    -o-user-select: none;
    color: #404040;
    font-weight: 600;
    user-select: none;
  }

  .decrease {
    border-right: 1px solid #CCC;
    cursor: pointer;
    float: left;
    height: 20px;
    line-height: 20px;
    text-align: center;
    width: 20px;

    &.disabled {
      color: #CCC;
      cursor: default;
    }
  }
  
  .alignment {
    border: none;
    float: left;
    width: 40px;
    height: 20px;
    padding: 0px 3px;
    text-align: center;
    line-height: 20px;
  }

  .increase {
    cursor: pointer;
    text-align: center;
    width: 20px;
    height: 20px;
    line-height: 20px;
    border-left: 1px solid #CCC;
    float: right;

    &.disabled {
      color: #CCC;
      cursor: default;
    }
  }

  .mask {
    background: rgba(0, 0, 0, 0);
    position: fixed;
    width: 100%;
    height: 100%;
    top: 0px;
    left: 0px;
    z-index: 10;
  } 
}

.clear {
  clear: both;
}
</style>